package vn.edu.thptduongbachmai.common;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 *
 * @author tiennv4
 */
public class ConcurrentLRUCache<Key, Value> {

	private final int _maxSize;
	private ConcurrentHashMap<Key, Value> _map;
	private ConcurrentLinkedQueue<Key> _queue;

	public ConcurrentLRUCache(final int maxSize) {
		this._maxSize = maxSize;
		_map = new ConcurrentHashMap<Key, Value>(maxSize);
		_queue = new ConcurrentLinkedQueue<Key>();
	}

	/**
	 * @param key - may not be null!
	 * @param value - may not be null!
	 */
	public boolean put(final Key key, final Value value) {
		boolean ret = false;
		if (_map.containsKey(key)) {
			_queue.remove(key); // remove the key from the FIFO queue
		}

		while (_queue.size() >= _maxSize) {
			Key oldestKey = _queue.poll();
			if (null != oldestKey) {
				_map.remove(oldestKey);
			}
		}
		if (_queue.add(key)) {
			_map.put(key, value);
		}
		return ret;
	}

	public boolean containsKey(final Key key) {
		if (_map.containsKey(key)) {
			return true;
		}
		return false;
	}

	public Value remove(final Key key) {
		if (_map.containsKey(key)) {
			_queue.remove(key); // remove the key from the FIFO queue
			return _map.remove(key);
		}
		return null;
	}

	/**
	 * @param key - may not be null!
	 * @return the value associated to the given key or null
	 */
	public Value get(final Key key) {
		return _map.get(key);
	}
}